package com.ruoyi.jt808.util.abandon;

import java.util.*;

public class JT808DeepParser {

    public static void main(String[] args) {
        String packet = "7E020000EE0610006515543A79000000000000080001FADDCD0669529A0000000000002510071141150104000021FF30011F310100EBC4000C00B28986084810247076538700060089FFFFFFFF000600C5FFFFFFF70004002D0E58000300A828000B00D801CC0090830B3D3419001100D5383631303134303738373935353937007000B90545383A32323A38313A43393A46453A44302C2D37332C34343A44463A36353A39363A37373A30322C2D37332C32343A39373A34353A34333A36363A43382C2D37342C31363A44383A36343A31303A33433A41462C2D38392C31433A37333A45323A44313A35423A32392C2D39330007002A000000000AD37E";

        try {
            deepParsePacket(packet);
            byte[] data = unescapePacket(hexStringToByteArray(packet));
            parseEBInDetail(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deepParsePacket(String packet) {
        System.out.println("=== JT808数据包深度解析 ===\n");

        // 去除首尾7E
        String content = packet.substring(2, packet.length() - 2);
        System.out.println("原始数据包长度: " + packet.length() + "字符");
        System.out.println("去除首尾后长度: " + content.length() + "字符");

        // 转义还原
        byte[] data = unescapePacket(hexStringToByteArray(content));
        System.out.println("转义还原后数据长度: " + data.length + "字节\n");

        // 打印完整的16进制数据
        System.out.println("=== 完整数据16进制转储 ===");
        printHexDump(data);

        // 深度解析消息结构
        deepParseMessageStructure(data);
    }

    private static void deepParseMessageStructure(byte[] data) {
        System.out.println("\n=== 消息结构深度解析 ===");

        int offset = 0;

        // 1. 解析消息头
        System.out.println("【消息头 - 偏移量: 0x" + String.format("%02X", offset) + "】");
        int msgId = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        System.out.println("消息ID: 0x" + String.format("%04X", msgId));
        offset += 2;

        int msgBodyProps = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        int bodyLength = msgBodyProps & 0x03FF;
        System.out.println("消息体属性: 0x" + String.format("%04X", msgBodyProps) + " (长度: " + bodyLength + ")");
        offset += 2;

        // 终端手机号
        StringBuilder terminalId = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            terminalId.append(String.format("%02X", data[offset + i]));
        }
        System.out.println("终端手机号: " + terminalId.toString());
        offset += 6;

        int msgSeq = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        System.out.println("消息流水号: " + msgSeq);
        offset += 2;

        System.out.println("消息头结束，偏移量: 0x" + String.format("%02X", offset));

        // 2. 解析位置基本信息
        System.out.println("\n【位置基本信息 - 偏移量: 0x" + String.format("%02X", offset) + "】");

        // 报警标志
        long alarmFlag = 0;
        for (int i = 0; i < 4; i++) {
            alarmFlag = (alarmFlag << 8) | (data[offset + i] & 0xFF);
        }
        System.out.println("报警标志: 0x" + Long.toHexString(alarmFlag));
        offset += 4;

        // 状态
        long status = 0;
        for (int i = 0; i < 4; i++) {
            status = (status << 8) | (data[offset + i] & 0xFF);
        }
        System.out.println("状态: 0x" + Long.toHexString(status));
        offset += 4;

        // 纬度
        int latitude = (data[offset] & 0xFF) << 24 | (data[offset + 1] & 0xFF) << 16 |
                (data[offset + 2] & 0xFF) << 8 | (data[offset + 3] & 0xFF);
        System.out.println("纬度: " + latitude + " (" + (latitude / 1000000.0) + "°)");
        offset += 4;

        // 经度
        int longitude = (data[offset] & 0xFF) << 24 | (data[offset + 1] & 0xFF) << 16 |
                (data[offset + 2] & 0xFF) << 8 | (data[offset + 3] & 0xFF);
        System.out.println("经度: " + longitude + " (" + (longitude / 1000000.0) + "°)");
        offset += 4;

        // 高程
        int altitude = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        System.out.println("高程: " + altitude + "米");
        offset += 2;

        // 速度
        int speed = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        System.out.println("速度: " + speed + " (" + (speed / 10.0) + "km/h)");
        offset += 2;

        // 方向
        int direction = (data[offset] & 0xFF) << 8 | (data[offset + 1] & 0xFF);
        System.out.println("方向: " + direction + "°");
        offset += 2;

        // 时间
        String time = bcdToString(data, offset, 6);
        System.out.println("时间(BCD): " + time);
        offset += 6;

        System.out.println("位置基本信息结束，偏移量: 0x" + String.format("%02X", offset));

        // 3. 深度解析附加信息
        System.out.println("\n【附加信息深度解析 - 偏移量: 0x" + String.format("%02X", offset) + "】");
        System.out.println("剩余数据长度: " + (data.length - offset) + "字节");

        deepParseExtraInfo(data, offset);
    }

    private static void deepParseExtraInfo(byte[] data, int startOffset) {
        int offset = startOffset;
        int extraCount = 0;

        System.out.println("\n开始遍历附加信息:");

        while (offset < data.length) {
            int type = data[offset] & 0xFF;

            if (type == 0) {
                System.out.println("遇到结束标志(0x00)，附加信息解析结束");
                break;
            }

            if (offset + 1 >= data.length) {
                System.out.println("数据长度不足，无法读取长度字段");
                break;
            }

            int length = data[offset + 1] & 0xFF;

            if (offset + 2 + length > data.length) {
                System.out.printf("附加项0x%02X 长度超出数据范围，预期长度: %d，实际剩余: %d\n",
                        type, length, data.length - offset - 2);

                if (type == 0xEB) {
                    System.out.println(">>> 找到0xEB附加信息! <<<");

                    extraCount++;
                    byte[] extraData = new byte[length];
                    System.arraycopy(data, offset + 2, extraData, 0, length-1);

                    parseEBInDetail(extraData);
                }

                //break;
            }

            extraCount++;
            byte[] extraData = new byte[length];
            System.arraycopy(data, offset + 2, extraData, 0, length);

            System.out.printf("\n【附加项 #%d - 偏移量: 0x%02X】\n", extraCount, offset);
            System.out.printf("类型: 0x%02X\n", type);
            System.out.printf("长度: %d字节\n", length);
            System.out.printf("数据: %s\n", bytesToHex(extraData));

            // 特别关注0xEB
            if (type == 0xEB) {
                System.out.println(">>> 找到0xEB附加信息! <<<");
                parseEBInDetail(extraData);
            }

            offset += 2 + length;
            System.out.printf("下一项偏移量: 0x%02X\n", offset);
        }

        System.out.println("\n总计找到 " + extraCount + " 个附加信息项");

        // 如果没找到0xEB，尝试搜索整个数据包
        if (!containsEB(data, startOffset)) {
            System.out.println("\n=== 深度搜索0xEB ===");
            searchForEBInWholePacket(data);
        }
    }



    private static boolean containsEB(byte[] data, int startOffset) {
        for (int i = startOffset; i < data.length - 1; i++) {
            if ((data[i] & 0xFF) == 0xEB) {
                return true;
            }
        }
        return false;
    }

    private static void searchForEBInWholePacket(byte[] data) {
        System.out.println("在整个数据包中搜索0xEB...");

        for (int i = 0; i < data.length; i++) {
            if ((data[i] & 0xFF) == 0xEB) {
                System.out.printf("在偏移量 0x%02X 找到0xEB\n", i);

                // 检查是否有足够的长度字段
                if (i + 1 < data.length) {
                    int length = data[i + 1] & 0xFF;
                    System.out.printf("长度字段: %d字节\n", length);

                    if (i + 2 + length <= data.length) {
                        byte[] ebData = new byte[length];
                        System.arraycopy(data, i + 2, ebData, 0, length);
                        System.out.printf("EB数据: %s\n", bytesToHex(ebData));
                        parseEBInDetail(ebData);
                    } else {
                        System.out.println("数据长度不足，无法提取完整EB数据");
                    }
                }
                return;
            }
        }

        System.out.println("在整个数据包中未找到0xEB");

        // 搜索可能的转义数据
        System.out.println("\n搜索转义的EB数据(7D 01 EB或7D 02 EB)...");
        for (int i = 0; i < data.length - 2; i++) {
            if ((data[i] & 0xFF) == 0x7D &&
                    ((data[i + 1] & 0xFF) == 0x01 || (data[i + 1] & 0xFF) == 0x02) &&
                    (data[i + 2] & 0xFF) == 0xEB) {
                System.out.printf("在偏移量 0x%02X 找到转义的0xEB数据\n", i);
            }
        }
    }

    private static void printHexDump(byte[] data) {
        for (int i = 0; i < data.length; i += 16) {
            System.out.printf("%04X: ", i);

            // 16进制显示
            for (int j = 0; j < 16; j++) {
                if (i + j < data.length) {
                    System.out.printf("%02X ", data[i + j]);
                } else {
                    System.out.print("   ");
                }
            }

            System.out.print(" ");

            // ASCII显示
            for (int j = 0; j < 16; j++) {
                if (i + j < data.length) {
                    byte b = data[i + j];
                    if (b >= 32 && b <= 126) {
                        System.out.print((char) b);
                    } else {
                        System.out.print(".");
                    }
                }
            }
            System.out.println();
        }
    }

    // 工具方法
    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    private static byte[] unescapePacket(byte[] data) {
        List<Byte> result = new ArrayList<>();
        for (int i = 0; i < data.length; i++) {
            if (data[i] == 0x7D) {
                if (i + 1 < data.length) {
                    if (data[i + 1] == 0x01) {
                        result.add((byte) 0x7D);
                    } else if (data[i + 1] == 0x02) {
                        result.add((byte) 0x7E);
                    } else {
                        // 未知的转义序列，保持原样
                        result.add(data[i]);
                    }
                    i++;
                } else {
                    result.add(data[i]);
                }
            } else {
                result.add(data[i]);
            }
        }

        byte[] unescaped = new byte[result.size()];
        for (int i = 0; i < result.size(); i++) {
            unescaped[i] = result.get(i);
        }
        return unescaped;
    }

    private static String bcdToString(byte[] data, int offset, int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(String.format("%02X", data[offset + i]));
        }
        return sb.toString();
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }

    static class AdditionalItem {
        int id;
        int length;
        byte[] data;

        AdditionalItem(int id, int length, byte[] data) {
            this.id = id;
            this.length = length;
            this.data = data;
        }
    }

    private static void parseEBInDetail(byte[] ebData) {
        System.out.println("\n【0xEB附加信息详细解析】");
        System.out.println("数据长度: " + ebData.length + "字节");
        System.out.println("完整数据: " + bytesToHex(ebData));
       /* String hexData = bytesToHex(ebData);
        String hexString = hexData.replaceAll(" ", "");
        System.out.println(hexString);*/
        String hexString = "7E020000EE0610006515543A79000000000000080001FADDCD0669529A0000000000002510071141150104000021FF30011F310100EBC4000C00B28986084810247076538700060089FFFFFFFF000600C5FFFFFFF70004002D0E58000300A828000B00D801CC0090830B3D3419001100D5383631303134303738373935353937007000B90545383A32323A38313A43393A46453A44302C2D37332C34343A44463A36353A39363A37373A30322C2D37332C32343A39373A34353A34333A36363A43382C2D37342C31363A44383A36343A31303A33433A41462C2D38392C31433A37333A45323A44313A35423A32392C2D39330007002A000000000AD37E";

        hexString= hexString.substring(hexString.indexOf("0104"));
        System.out.println("测试:"+hexString);

        int position = hexString.indexOf("00A8");
        if (position != -1) {
            System.out.println("找到 '00A8' 在位置: " + position);
            System.out.println("字节位置: " + (position / 2));

            System.out.println("电量字符: " + hexString.substring(position,position+2));

            int afterPosition = position + 4; // 00A8 占4个字符
            if (afterPosition + 2 <= hexString.length()) {
                String nextTwoChars = hexString.substring(afterPosition, afterPosition + 2);
                System.out.println("00A8 后面的两位字符是: " + nextTwoChars);

                // 显示完整上下文
                showFullContext(hexString, position, 4);

                // 解析含义
                //parseMeaning(nextTwoChars);

                int decimalValue = Integer.parseInt(nextTwoChars, 16);
                System.out.println("电量百分比: " + decimalValue);
            } else {
                System.out.println("00A8 后面没有足够的字符");
            }

        } else {
            System.out.println("未找到 '0003A8'");

        }

    }

    private static void showFullContext(String hexString, int position, int patternLength) {
        int start = Math.max(0, position - 10);
        int end = Math.min(hexString.length(), position + patternLength + 10);

        System.out.println("完整上下文:");
        String context = hexString.substring(start, end);
        System.out.println("..." + context + "...");

        // 标记位置
        System.out.print("   ");
        int markerPos = position - start;
        for (int i = 0; i < markerPos; i++) {
            System.out.print(" ");
        }
        System.out.print("00A8");

        // 标记后面的字符
        if (position + patternLength + 2 <= end) {
            for (int i = 0; i < 2; i++) {
                System.out.print(" ");
            }
            System.out.print("^^");
        }
        System.out.println();
    }

    private static void parseMeaning(String twoChars) {
        System.out.println("\n=== 字符解析 ===");
        System.out.println("十六进制: " + twoChars);

        // 转换为十进制
        int decimalValue = Integer.parseInt(twoChars, 16);
        System.out.println("十进制: " + decimalValue);

        // 转换为ASCII字符（如果是可打印字符）
        if (decimalValue >= 32 && decimalValue <= 126) {
            char asciiChar = (char) decimalValue;
            System.out.println("ASCII字符: '" + asciiChar + "'");
        }

        // 分析可能的含义
        System.out.println("\n可能的含义:");
        if (decimalValue <= 100) {
            System.out.println("- 电量百分比: " + decimalValue + "%");
        }
    }
}